#include "JLog.h"

#include <QFile>
#include <QTextStream>
#include <QStringList>
#include <QDateTime>


JLog::JLog(void):
m_HighestError(JLOG_INFO)
{ }

JLog::~JLog()
{ }

JLog& JLog::Instance(void)
{
	static JLog m_Log;
	return m_Log;
}

void JLog::PostSub(const QString &msg, unsigned short msgType)
{
	m_LastEntry.mTime = getTimeTick();
	m_LastEntry.mType = msgType;
	//mHighestError = (mType > mHighestError) ? mType : JLOG_SUCCESS;
	if(msgType > m_HighestError && msgType != JLOG_SUCCESS) m_HighestError = msgType;
	m_LastEntry.mMsg = msg;
	m_LastEntry.bSubEntry = true;
	m_LogEntryList.append(m_LastEntry);
}

void JLog::Post(const QString &msg, unsigned short msgType)
{
	m_LastEntry.mTime = getTimeTick();
	if (msgType <= m_HighestError) m_LastEntry.mType = m_HighestError;
	else m_LastEntry.mType = msgType;
	m_LastEntry.mMsg = msg;
	m_LastEntry.bSubEntry = false;
	m_LogEntryList.append(m_LastEntry);
	emit sendList(&m_LogEntryList);
	// log to file
	writeToFile(QString("- ")+getTimeTick()+msgTypeToString(m_LogEntryList.last().mType)+m_LogEntryList.last().mMsg);
	for (int ii = 0; ii < m_LogEntryList.size()-1; ++ii)
	{
		writeToFile(QString("    ") + getTimeTick() + msgTypeToString(m_LogEntryList.at(ii).mType) + m_LogEntryList.at(ii).mMsg);
	}
	m_LogEntryList.clear();
	m_HighestError = JLOG_INFO;
}

void JLog::LogToFile( const QString &msg, unsigned short msgType /*= JLOG_SUCCESS */ )
{
	writeToFile(QString("- ") + getTimeTick() + msgTypeToString(msgType) + msg);
}

QString JLog::msgTypeToString(unsigned short msgType)
{
	QStringList buffer;
	buffer << " " << " " << " [WARNING] " << " [ERROR] " << " [CRITICAL] ";
	return buffer.at(msgType);
}

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)

#include <windows.h>

QString JLog::getTimeTick(int tickResolution)
{
	const int MAX_LEN = 200;
	char buffer[MAX_LEN];
	if (GetTimeFormatA(LOCALE_USER_DEFAULT, 0, 0, 
		"HH':'mm':'ss", buffer, MAX_LEN) == 0)
		return QString("Error in getTimeTick()");

	char result[100] = {0};
	static DWORD first = GetTickCount();
	std::sprintf(result, "%s.%03ld", buffer, (long)(GetTickCount() - first) % tickResolution); 
	return QString::fromStdString(result);
}

#else

#include <sys/time.h>

QString JLog::getTimeTick(int tickResolution)
{
	char buffer[11];
	time_t t;
	time(&t);
	tm r = {0};
	strftime(buffer, sizeof(buffer), "%X", localtime_r(&t, &r));
	struct timeval tv;
	gettimeofday(&tv, 0);
	char result[100] = {0};
	std::sprintf(result, "%s.%03ld", buffer, (long)tv.tv_usec / tickResolution); 
	return QString::fromStdString(result);
}

#endif //WIN32

//#include <iostream>
//#include <fstream>
//#include <sstream>

void JLog::writeToFile(const QString &msg)
{
	/*static std::ofstream logFile;
	logFile.open ("JointMD.log", std::ios_base::app);

	if (logFile.is_open()) {
		logFile << mMsg.toStdString() << std::endl;
		logFile.close();
	}*/
	QFile file(m_CurrentLogFileName);
	file.open(QIODevice::WriteOnly | QIODevice::Append | QIODevice::Text);
	//mFile.write(mMsg.toAscii());
	QTextStream mOutput(&file);
	mOutput << msg << endl;
	file.close();
}

void JLog::ClearLog(const QString& fileName)
{
	QDateTime dateTime;
	m_CurrentLogFileName = fileName;
	QFile file(fileName);
	file.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text);
	QTextStream mOutput(&file);
	mOutput << "************ Logged " << dateTime.currentDateTime().toString() << " ************\n" << endl;
	file.close();
	/*std::ofstream cleanLog;
	cleanLog.open("JointMD.log",std::ios_base::trunc);

	if (cleanLog.is_open())
	{
		cleanLog << "************ JointMD Log " << getTime().toStdString() <<" ************" << std::endl;
		cleanLog.close();
	}*/
}